#include "Putere.h"
#include "LogaritmN.cpp"
long double Putere::calcul(long double aux1, long double aux2)
{
    if (aux1 < 0 || ISZERO(aux1))
    {
        if (ISZERO(aux2 - ROUND(aux2)))
        {
            int x = ROUND(aux2);
            int sgn;
            long double rez = 1;

            if (x < 0)
            {
                sgn = -1; x *= -1;
            }
            else sgn = 1;

            while (sgn * x > 0)
            {
                rez *= aux1;
                x -= sgn;
            }
            if (sgn < 0)
                return Impartit::calcul(1, rez);
            else return rez;
        }

        std::cout<<"Nu se poate ridica la putere un numar negativ..";
        return 0;
    }

    return powl(aux1, aux2);
}

long double Putere::calcul()
{
    long double aux;

    if (!fStang || !fDrept)
        exit(1);

    return calcul(fStang->calcul(), fDrept->calcul());
}

char *Putere::derivare()
{
    char *aux1, *aux11, *aux2, *aux22, *aux, *aux00, *aux01;
    int nrP;

    if (!fStang || !fDrept)
        exit(1);

    aux1 = fStang->derivare();
    aux11 = fStang->toString();
    aux2 = fDrept->derivare();
    aux22 = fDrept->toString();


    if (!strcmp(aux1, "0"))
    {
        delete aux1; aux1 = toString();
        nrP = aux1[0] == '(' ? 0 : 2;

        aux00 = LogaritmN::concatTermeni(aux11);
        aux01 = Inmultit::concatTermeni(aux00, aux2);
        aux = Inmultit::concatTermeni(aux01, aux1);
    }
    else
    {
        long double daux = fDrept->calcul();
        char *aux3;

        aux3 = ftoa(daux - 1);

        aux00 = concatTermeni(aux11, aux3);
        aux01 = Inmultit::concatTermeni(aux22, aux00);
        aux = Inmultit::concatTermeni(aux01, aux1);
        delete aux3;
    }

    delete aux1; delete aux2; delete aux11; delete aux22; delete aux00; delete aux01;
    return aux;
}

long double Putere::calculDerivata()
{
    char *aux;
    long double val;

    if (!fStang || !fDrept)
        exit(1);
    aux = fStang->derivare();

    if (!strcmp(aux, "0"))
        val = Inmultit::calcul(Inmultit::calcul(LogaritmN::calcul(fStang->calcul()),
                    calcul()), fDrept->calculDerivata());
    else
        val = Inmultit::calcul(Inmultit::calcul(Putere::calcul(val = fStang->calcul(),
                Minus::calcul(fDrept->calcul(), 1)), fDrept->calcul()),
                    fStang->calculDerivata());

    delete aux;
    return val;
}

char *Putere::toString()
{
    char *aux, *aux1, *aux2;

    if (!fStang || !fDrept)
        exit(1);

    aux1 = fStang->toString();
    aux2 = fDrept->toString();

    aux = concatTermeni(aux1, aux2);
    delete aux1; delete aux2;

    return aux;
}

char *Putere::concatTermeni(char *aux1, char *aux2)
{
    char *aux;

    if (!strcmp(aux1, "0")) aux = cpystr("0");
    else if (!strcmp(aux2, "0")) aux = cpystr("1");
    else if (!strcmp(aux2, "1")) aux = cpystr(aux1);
    else
    {
        aux = new char[strlen(aux1) + strlen(aux2) + 4];
        strcpy(aux, "(");
        strcat(aux, aux1); strcat(aux, "^"); strcat(aux, aux2); strcat(aux, ")");
    }

    return aux;
}
